home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************
- *
- * SeeILBM.c
- * Read an ILBM file and display as a screen/window until closed.
- * Simulated close gadget in upper left corner of window.
- * Clicking below title bar area toggles screen bar for dragging.
- *
- * By Carolyn Scheppner CBM 03/15/86
- * Modified 09/02/86 - Only global frame is iFrame
- * Use message->MouseX and Y
- * Wait() for IDCMP
- *
- * Based on early ShowILBM.c 11/12/85
- * By Jerry Morrison, Steve Shaw, and Steve Hayes, Electronic Arts.
- * This software is in the public domain.
- *
- * >>NOTE<<: This example must be linked with additional IFF rtn files.
- * See linkage information below.
- *
- * The IFF reader portion is essentially a recursive-descent parser.
- * This program will look into a CAT or LIST to find a FORM ILBM, but it
- * won't look inside another FORM type for a nested FORM ILBM.
- *
- * The display portion is specific to the Commodore Amiga computer.
- *
- * Linkage Information:
- *
- * FROM LStartup.obj, SeeILBM.o, iffr.o, ilbmr.o, unpacker.o
- * TO SeeILBM
- * LIBRARY LC.lib, Amiga.lib
- *
- **************************************************************************/
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <libraries/dos.h>
- #include <graphics/gfxbase.h>
- #include <graphics/rastport.h>
- #include <graphics/gfx.h>
- #include <graphics/view.h>
- #include <workbench/startup.h>
- #include <intuition/intuition.h>
- #include <lattice/stdio.h>
-
- #include "iff/ilbm.h"
-
- /* This example's max number of planes in a bitmap. Could use MaxAmDepth. */
- #define EXDepth 5
- #define maxColorReg (1<<EXDepth)
- #define MIN(a,b) ((a)<(b)?(a):(b))
-
- #define SafeFreeMem(p,q) {if(p)FreeMem(p,q);}
-
- /* Define the size of a temp buffer used in unscrambling the ILBM rows.*/
- #define bufSz 512
-
- /* general usage pointers */
- struct GfxBase *GfxBase;
- struct IntuitionBase *IntuitionBase;
- struct IntuiMessage *message;
-
- /* Globals for displaying an image */
- struct Screen *screen1;
- struct Window *window1;
- struct RastPort *rport1;
- struct ViewPort *vport1;
-
- struct BitMap tBitMap; /* Temp BitMap struct for small pics */
-
- /* For WorkBench startup */
- extern struct WBStartup *WBenchMsg;
- BOOL fromWB;
- struct FileLock *startLock, *newLock;
-
- /* Other globals */
- int i, error;
- BYTE c;
- BOOL TBtoggle, Done;
- ULONG class, code, pBytes;
- SHORT mouseX, mouseY;
-
- /* Structures for new Screen, new Window */
-
- struct TextAttr TextFont = {
- "topaz.font", /* Font Name */
- TOPAZ_EIGHTY, /* Font Height */
- FS_NORMAL, /* Style */
- FPF_ROMFONT, /* Preferences */
- };
-
- struct NewScreen ns = {
- 0, 0, /* LeftEdge and TopEdge */
- 0, 0, /* Width and Height */
- 0, /* Depth */
- -1, -1, /* DetailPen and BlockPen */
- NULL, /* Special display modes */
- CUSTOMSCREEN, /* Screen Type */
- &TextFont, /* Use my font */
- NULL, /* Title */
- NULL, /* No gadgets yet */
- NULL, /* Ptr to CustomBitmap */
- };
-
- struct NewWindow nw = {
- 0, 0, /* LeftEdge and TopEdge */
- 0, 0, /* Width and Height */
- -1, -1, /* DetailPen and BlockPen */
- MOUSEBUTTONS, /* IDCMP Flags */
- ACTIVATE
- |BACKDROP
- |BORDERLESS, /* Flags */
- NULL, NULL, /* Gadget and Image pointers */
- NULL, /* Title string */
- NULL, /* Put Screen ptr here */
- NULL, /* SuperBitMap pointer */
- 0, 0, /* MinWidth and MinHeight */
- 0, 0, /* MaxWidth and MaxHeight */
- CUSTOMSCREEN, /* Type of window */
- };
-
- USHORT allBgColor[32];
-
-
- /* Message strings for IFFP codes. */
- char MsgOkay[] = {"(IFF_OKAY) No FORM ILBM in the file." };
- char MsgEndMark[] = {"(END_MARK) How did you get this message?" };
- char MsgDone[] = {"(IFF_DONE) All done."};
- char MsgDos[] = {"(DOS_ERROR) The DOS returned an error." };
- char MsgNot[] = {"(NOT_IFF) Not an IFF file." };
- char MsgNoFile[] = {"(NO_FILE) No such file found." };
- char MsgClientError[] = {"(CLIENT_ERROR) ShowILBM bug or insufficient RAM."};
- char MsgForm[] = {"(BAD_FORM) A malformed FORM ILBM." };
- char MsgShort[] = {"(SHORT_CHUNK) A malformed FORM ILBM." };
- char MsgBad[] = {"(BAD_IFF) A mangled IFF file." };
-
- /* THESE MUST APPEAR IN RIGHT ORDER!! */
- char *IFFPMessages[-LAST_ERROR+1] = {
- /*IFF_OKAY*/ MsgOkay,
- /*END_MARK*/ MsgEndMark,
- /*IFF_DONE*/ MsgDone,
- /*DOS_ERROR*/ MsgDos,
- /*NOT_IFF*/ MsgNot,
- /*NO_FILE*/ MsgNoFile,
- /*CLIENT_ERROR*/ MsgClientError,
- /*BAD_FORM*/ MsgForm,
- /*SHORT_CHUNK*/ MsgShort,
- /*BAD_IFF*/ MsgBad
- };
-
- /*------------ ILBM reader -----------------------------------------------*/
- /* ILBMFrame is our "client frame" for reading FORMs ILBM in an IFF file.
- * We allocate one of these on the stack for every LIST or FORM encountered
- * in the file and use it to hold BMHD & CMAP properties. We also allocate
- * an initial one for the whole file.
- * We allocate a new GroupContext (and initialize it by OpenRIFF or
- * OpenRGroup) for every group (FORM, CAT, LIST, or PROP) encountered. It's
- * just a context for reading (nested) chunks.
- *
- * If we were to scan the entire example file outlined below:
- * reading proc(s) new new
- *
- * --whole file-- ReadPicture+ReadIFF GroupContext ILBMFrame
- * CAT ReadICat GroupContext
- * LIST GetLiILBM+ReadIList GroupContext ILBMFrame
- * PROP ILBM GetPrILBM GroupContext
- * CMAP GetCMAP
- * BMHD GetBMHD
- * FORM ILBM GetFoILBM GroupContext ILBMFrame
- * BODY GetBODY
- * FORM ILBM GetFoILBM GroupContext ILBMFrame
- * BODY GetBODY
- * FORM ILBM GetFoILBM GroupContext ILBMFrame
- */
- typedef struct {
- ClientFrame clientFrame;
- UBYTE foundBMHD;
- UBYTE nColorRegs;
- BitMapHeader bmHdr;
- Color4 colorMap[maxColorReg];
- /* If you want to read any other property chunks, e.g. GRAB or CAMG, add
- * fields to this record to store them. */
- } ILBMFrame;
-
-
- /* NOTE: For a simple version of this program, set Fancy to 0.
- * That'll compile a program that skips all LISTs and PROPs in the input
- * file. It will look in CATs for FORMs ILBM. That's suitable for most uses.
- *
- * For a fancy version that handles LISTs and PROPs, set Fancy to 1. */
-
- #define Fancy 1
-
- /* Modified by C. Scheppner */
- /* iFrame made global - moved from ReadPicture() */
-
- ILBMFrame iFrame; /* top level client frame */
-
-
- /** main() ****************************************************************/
- main(argc, argv)
- int argc;
- char **argv;
- {
- LONG file;
- IFFP iffp = NO_FILE;
- struct WBArg *arg;
- char *filename;
-
- fromWB = (argc==0) ? TRUE : FALSE;
-
- if(argc>1) /* Passed filename via command line */
- {
- filename = argv[1];
- }
- else if ((argc==0)&&(WBenchMsg->sm_NumArgs > 1))
- { /* Passed filename via WorkBench */
- arg = WBenchMsg->sm_ArgList;
- arg++;
- filename = (char *)arg->wa_Name;
- newLock = (struct FileLock *)arg->wa_Lock;
- startLock = (struct FileLock *)CurrentDir(newLock);
- }
- else if (argc==1) /* From CLI but no filename */
- cleanexit("Usage: 'SeeILBM filename'\n");
- else /* From WB but no filename */
- cleanexit("\nClick ONCE on SeeILBM\nSHIFT and DoubleClick on Pic\n");
-
-
-
- if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0)))
- cleanexit("Can't open graphics library\n");
-
- if(!(IntuitionBase=
- (struct IntuitionBase *)OpenLibrary("intuition.library",0)))
- cleanexit("Can't open graphics library\n");
-
- if(file = Open(filename, MODE_OLDFILE))
- {
- printf("\nCLICK PIC TOP LEFT TO END DISPLAY\n");
- printf("CLICK LOWER TO TOGGLE DRAG BAR\n");
- Delay(150); /* wait about 3 seconds to give person time to read it */
-
- iffp = ReadPicture(file);
- Close(file);
- if (iffp == IFF_DONE)
- {
- error = DisplayPic(&iFrame);
- if(error) cleanexit("Can't open screen or window\n");
-
- TBtoggle = FALSE; /* Title bar toggle */
- Done = FALSE; /* Close flag */
- while (!Done)
- {
- Wait(1<<window1->UserPort->mp_SigBit);
- chkmsg();
- }
- }
- else cleanexit(IFFPMessages[-iffp]);
- }
- else cleanexit("Picture file not found.\n");
-
- cleanup();
- }
-
-
- chkmsg()
- {
- while(message=(struct IntuiMessage *)GetMsg(window1->UserPort))
- {
- class = message->Class;
- code = message->Code;
- mouseX = message->MouseX;
- mouseY = message->MouseY;
-
- ReplyMsg(message);
- switch(class)
- {
- case MOUSEBUTTONS:
- if ((code == SELECTDOWN)&&
- (mouseX < 10)&&(mouseY<10))
- {
- Done = TRUE;
- }
- else if ((code == SELECTDOWN)&&
- (mouseY>10)&&(TBtoggle==FALSE))
- {
- TBtoggle = TRUE;
- ShowTitle(screen1,TRUE);
- }
- else if ((code == SELECTDOWN)&&
- (mouseY>10)&&(TBtoggle==TRUE))
- {
- TBtoggle = FALSE;
- ShowTitle(screen1,FALSE);
- }
- break;
- default:
- printf("Unknown IDCMP message\n");
- }
- }
- }
-
-
- cleanexit(errstr)
- char *errstr;
- {
- printf("\n %s \n",errstr);
- cleanup();
- if (fromWB) /* Wait so user can read messages */
- {
- printf("\nPRESS RETURN TO CLOSE THIS WINDOW\n");
- while ((c=getchar()) != '\n');
- }
- exit();
- }
-
- cleanup()
- {
- /* tBitMap planes were deallocated in DisplayPic() */
- if (window1)
- {
- while(message=(struct IntuiMessage *)GetMsg(window1->UserPort))
- {
- ReplyMsg(message);
- }
- CloseWindow(window1);
- }
- if (screen1) CloseScreen(screen1);
- if (IntuitionBase) CloseLibrary(IntuitionBase);
- if (GfxBase) CloseLibrary(GfxBase);
- if (newLock != startLock) CurrentDir(startLock);
- }
-
-
- /** getBitMap() *********************************************************
- *
- * Open screen or temp bitmap.
- * Returns ptr destBitMap or 0 = error
- *
- *************************************************************************/
- struct BitMap *getBitMap(ptilbmFrame)
- ILBMFrame *ptilbmFrame;
- {
- int i, nPlanes, plsize;
- SHORT sWidth, sHeight, dWidth, dHeight;
- struct BitMap *destBitMap;
-
- sWidth = ptilbmFrame->bmHdr.w;
- sHeight = ptilbmFrame->bmHdr.h;
- dWidth = ptilbmFrame->bmHdr.pageWidth;
- dHeight = ptilbmFrame->bmHdr.pageHeight;
- nPlanes = MIN(ptilbmFrame->bmHdr.nPlanes, EXDepth);
-
- for (i = 0; i < ptilbmFrame->nColorRegs; i++)
- {
- allBgColor[i] = ptilbmFrame->colorMap[0];
- }
-
- ns.Width = dWidth;
- ns.Height = dHeight;
- ns.Depth = nPlanes;
-
- if (ptilbmFrame->bmHdr.pageWidth <= 320)
- ns.ViewModes = 0;
- else
- ns.ViewModes = HIRES;
-
- if (ptilbmFrame->bmHdr.pageHeight > 200)
- ns.ViewModes |= LACE;
-
- if ((screen1 = (struct Screen *)OpenScreen(&ns))==NULL) return(0);
-
- vport1 = &screen1->ViewPort;
- LoadRGB4(vport1, &allBgColor[0], ptilbmFrame->nColorRegs);
-
- nw.Width = dWidth;
- nw.Height = dHeight;
- nw.Screen = screen1;
-
- if ((window1 = (struct Window *)OpenWindow(&nw))==NULL) return(0);
-
- ShowTitle(screen1, FALSE);
-
- if ((sWidth == dWidth) && (sHeight == dHeight))
- {
- destBitMap = (struct BitMap *)screen1->RastPort.BitMap;
- }
- else
- {
- InitBitMap( &tBitMap,
- nPlanes,
- sWidth,
- sHeight);
-
- plsize = RowBytes(ptilbmFrame->bmHdr.w) * ptilbmFrame->bmHdr.h;
- if (tBitMap.Planes[0] =
- (PLANEPTR)AllocMem(nPlanes * plsize, MEMF_CHIP))
- {
- for (i = 1; i < nPlanes; i++)
- tBitMap.Planes[i] = (PLANEPTR)tBitMap.Planes[0] + plsize*i;
- destBitMap = &tBitMap;
- }
- else
- {
- return(0); /* can't allocate temp BitMap */
- }
- }
- return(destBitMap); /* destBitMap allocated */
- }
-
-
- /** DisplayPic() *********************************************************
- *
- * Display loaded bitmap. If tBitMap, first transfer to screen.
- *
- *************************************************************************/
- DisplayPic(ptilbmFrame)
- ILBMFrame *ptilbmFrame;
- {
- int i, row, byte, nrows, nbytes;
- struct BitMap *tbp, *sbp; /* temp and screen BitMap ptrs */
- UBYTE *tpp, *spp; /* temp and screen plane ptrs */
-
- if (tBitMap.Planes[0]) /* transfer from tBitMap if nec. */
- {
- tbp = &tBitMap;
- sbp = screen1->RastPort.BitMap;
- nrows = MIN(tbp->Rows, sbp->Rows);
- nbytes = MIN(tbp->BytesPerRow, sbp->BytesPerRow);
-
- for (i = 0; i < sbp->Depth; i++)
- {
- tpp = (UBYTE *)tbp->Planes[i];
- spp = (UBYTE *)sbp->Planes[i];
- for (row = 0; row < nrows; row++)
- {
- tpp = tbp->Planes[i] + (row * tbp->BytesPerRow);
- spp = sbp->Planes[i] + (row * sbp->BytesPerRow);
- for (byte = 0; byte < nbytes; byte++)
- {
- *spp++ = *tpp++;
- }
- }
- }
- /* Can now deallocate the temp BitMap */
- FreeMem(tBitMap.Planes[0],
- tBitMap.BytesPerRow * tBitMap.Rows * tBitMap.Depth);
- }
-
- vport1 = &screen1->ViewPort;
- LoadRGB4(vport1, ptilbmFrame->colorMap, ptilbmFrame->nColorRegs);
-
- return(0);
- }
-
-
- /** GetLiILBM() **********************************************************
- *
- * Called via ReadPicture to handle every LIST encountered in an IFF file.
- *
- *************************************************************************/
- #if Fancy
- IFFP GetLiILBM(parent)
- GroupContext *parent; {
- ILBMFrame newFrame; /* allocate a new Frame */
-
- newFrame = *(ILBMFrame *)parent->clientFrame; /* copy parent frame */
-
- return( ReadIList(parent, (ClientFrame *)&newFrame) );
- }
- #endif
-
-
- /** GetPrILBM() **********************************************************
- *
- * Called via ReadPicture to handle every PROP encountered in an IFF file.
- * Reads PROPs ILBM and skips all others.
- *
- *************************************************************************/
- #if Fancy
- IFFP GetPrILBM(parent)
- GroupContext *parent; {
- /*compilerBug register*/ IFFP iffp;
- GroupContext propContext;
- ILBMFrame *ilbmFrame = (ILBMFrame *)parent->clientFrame;
-
- if (parent->subtype != ID_ILBM)
- return(IFF_OKAY); /* just continue scaning the file */
-
- iffp = OpenRGroup(parent, &propContext);
- CheckIFFP();
-
- do switch (iffp = GetPChunkHdr(&propContext)) {
- case ID_BMHD: {
- ilbmFrame->foundBMHD = TRUE;
- iffp = GetBMHD(&propContext, &ilbmFrame->bmHdr);
- break; }
- case ID_CMAP: {
- ilbmFrame->nColorRegs = maxColorReg; /* room for this many */
- iffp = GetCMAP( &propContext, (WORD *)ilbmFrame->colorMap,
- &ilbmFrame->nColorRegs);
- break; }
-
- } while (iffp >= IFF_OKAY);/* loop if valid ID of ignored chunk or
- * subrtn returned IFF_OKAY (no errors).*/
-
- CloseRGroup(&propContext);
- return(iffp == END_MARK ? IFF_OKAY : iffp);
- }
- #endif
-
-
- /** GetFoILBM() **********************************************************
- *
- * Called via ReadPicture to handle every FORM encountered in an IFF file.
- * Reads FORMs ILBM and skips all others.
- * Inside a FORM ILBM, it stops once it reads a BODY. It complains if it
- * finds no BODY or if it has no BMHD to decode the BODY.
- *
- * Once we find a BODY chunk, we'll allocate the BitMap and read the image.
- *
- *
- *************************************************************************/
- IFFP GetFoILBM(parent)
- GroupContext *parent;
- {
- IFFP iffp;
- GroupContext formContext;
- ILBMFrame ilbmFrame;
- BYTE buffer[bufSz];
- struct BitMap *destBitMap;
-
- if (parent->subtype != ID_ILBM)
- return(IFF_OKAY); /* just continue scaning the file */
-
- ilbmFrame = *(ILBMFrame *)parent->clientFrame;
- iffp = OpenRGroup(parent, &formContext);
- CheckIFFP();
-
- do switch (iffp = GetFChunkHdr(&formContext)) {
- case ID_BMHD: {
- ilbmFrame.foundBMHD = TRUE;
- iffp = GetBMHD(&formContext, &ilbmFrame.bmHdr);
- break; }
- case ID_CMAP: {
- ilbmFrame.nColorRegs = maxColorReg; /* we have room for this many */
- iffp = GetCMAP(&formContext, (WORD *)ilbmFrame.colorMap,
- &ilbmFrame.nColorRegs);
- break; }
- case ID_BODY: {
- if (!ilbmFrame.foundBMHD)
- {
- iffp = BAD_FORM; /* No BMHD chunk! */
- }
- else
- {
- if(destBitMap=(struct BitMap *)getBitMap(&ilbmFrame))
- {
- iffp = GetBODY( &formContext,
- destBitMap,
- NULL,
- &ilbmFrame.bmHdr,
- buffer,
- bufSz);
- if (iffp == IFF_OKAY) iffp = IFF_DONE; /* Eureka */
- }
- else
- {
- iffp = CLIENT_ERROR; /* not enough RAM for the bitmap */
- }
- }
- break; }
-
- case END_MARK: {
- iffp = BAD_FORM;
- break; }
-
- } while (iffp >= IFF_OKAY); /* loop if valid ID of ignored chunk or a
- * subroutine returned IFF_OKAY (no errors).*/
-
- iFrame = ilbmFrame;
-
- if (iffp != IFF_DONE) return(iffp);
-
- CloseRGroup(&formContext);
- return(iffp);
- }
-
- /** Notes on extending GetFoILBM *****************************************
- *
- * To read more kinds of chunks, just add clauses to the switch statement.
- * To read more kinds of property chunks (GRAB, CAMG, etc.) add clauses to
- * the switch statement in GetPrILBM, too.
- *
- * To read a FORM type that contains a variable number of data chunks--e.g.
- * a FORM FTXT with any number of CHRS chunks--replace the ID_BODY case with
- * an ID_CHRS case that doesn't set iffp = IFF_DONE, and make the END_MARK
- * case do whatever cleanup you need.
- *
- *************************************************************************/
-
-
- /** ReadPicture() ********************************************************
- *
- * Read a picture from an IFF file, given a file handle open for reading.
- *
- * Modified by Carolyn Scheppner CBM 03-86
- * iFrame made global (above main)
- * Close(file) moved to main
- *
- *************************************************************************/
- IFFP ReadPicture(file)
- LONG file;
- {
- IFFP iffp = IFF_OKAY;
-
- #if Fancy
- iFrame.clientFrame.getList = GetLiILBM;
- iFrame.clientFrame.getProp = GetPrILBM;
- #else
- iFrame.clientFrame.getList = SkipGroup;
- iFrame.clientFrame.getProp = SkipGroup;
- #endif
- iFrame.clientFrame.getForm = GetFoILBM;
- iFrame.clientFrame.getCat = ReadICat ;
-
- /* Initialize the top-level client frame's property settings to the
- * program-wide defaults. This example just records that we haven't read
- * any BMHD property or CMAP color registers yet. For the color map, that
- * means the default is to leave the machine's color registers alone.
- * If you want to read a property like GRAB, init it here to (0, 0). */
- iFrame.foundBMHD = FALSE;
- iFrame.nColorRegs = 0;
-
- iffp = ReadIFF(file, (ClientFrame *)&iFrame);
- return(iffp);
- }
-
-
- oundBMHD